
// Definition about segment descriptor

#define SD_BASE_LOW(x)              ((x & 0x0000ffff) << 16)
#define SD_BASE_MID(x)              (x & 0x00ff0000)
#define SD_BASE_HIGH(x)             ((x & 0xff000000) << 24)

#define SD_LIMIT_LOW(x)             (x & 0x0000ffff)
#define SD_LIMIT_HIGH(x)            ((x & 0x000f0000) << 16)

#define SD_ACCESSED(x)              (x << 8)
#define SD_TYPE(x)                  (x << 8)
#define SD_RW(x)                    (X << 9)
#define SD_DIR_COM(x)               (x << 10)
#define SD_EXEC(x)                  (x << 11)
#define SD_S_TYPE(x)                (x << 12)   // set if defines a code- or data-segment, else for system segment
#define SD_DPL(x)                   (x << 13)
#define SD_PRESENT(x)               (x << 15)

#define SD_AVL(x)                   (x << 20)
#define SD_L(x)                     (x << 21)   // 64 bits mode
#define SD_DB(x)                    (x << 22)   // 32 bits mode
#define SD_GRAN(x)                  (x << 23)   // GRANULARITY FLAG, 0 if 1 B, 1 if 4 KIB

// Code- and Data-Segment Types
#define SEG_DATA_R                  0x0
#define SEG_DATA_RA                 0x1
#define SEG_DATA_RW                 0x2
#define SEG_DATA_RWA                0x3
#define SEG_DATA_RE                 0x4     // read only, expand down
#define SEG_DATA_REA                0x5
#define SEG_DATA_RWE                0x6
#define SEG_DATA_RWEA               0x7

#define SEG_CODE_E                  0x8     // execute only
#define SEG_CODE_EA                 0x9
#define SEG_CODE_RE                 0xa
#define SEG_CODE_REA                0xb
#define SEG_CODE_EC                 0xc
#define SEG_CODE_ECA                0xd
#define SEG_CODE_REC                0xe
#define SEG_CODE_RECA               0xf

// 4 initial segments
#define SD_CODE_R0                  (SD_DPL(0) | SD_TYPE(SEG_CODE_RE) | SD_PRESENT(1) | \
                                        SD_DB(1) | SD_GRAN(1) | SD_S_TYPE(1))
#define SD_CODE_R3                  (SD_DPL(3) | SD_TYPE(SEG_CODE_RE) | SD_PRESENT(1) | \
                                        SD_DB(1) | SD_GRAN(1) | SD_S_TYPE(1))
#define SD_DATA_R0                  (SD_DPL(0) | SD_TYPE(SEG_DATA_RW) | SD_PRESENT(1) | \
                                        SD_DB(1) | SD_GRAN(1) | SD_S_TYPE(1))  
#define SD_DATA_R3                  (SD_DPL(3) | SD_TYPE(SEG_DATA_RW) | SD_PRESENT(1) | \
                                        SD_DB(1) | SD_GRAN(1) | SD_S_TYPE(1))  

#define SD_LOW(a, b)                (a | b)


void _gdt_init();